package com.smzd.ccms.actions;

import java.util.Enumeration;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.smzd.ccms.business.ChannelService;
import com.smzd.ccms.core.CCMSConstant;
import com.smzd.ccms.core.CompletPluginManager;
import com.smzd.ccms.core.ViewMapResult;
import com.smzd.ccms.core.ViewMapper;
import com.smzd.ccms.core.ViewMapperCache;
import com.smzd.ccms.domain.Channel;
import com.smzd.ccms.domain.Site;
import com.smzd.ccms.exceptions.PageNotFoundException;
import com.smzd.framework.annotation.Access;
import com.smzd.framework.utils.JsonHelper;

@Controller
public class PortalController {
	@Autowired
	ChannelService channelService;

	/**
	 * 站点首页，默认站点需要一个栏目名字为welcome，如果没有，则应该找首页配置的栏目。<br>
	 * 不过目前没有实现找首页配置，只实现了配置哪个栏目可以作为首页。
	 * 
	 * @param model
	 * @param request
	 * @param site
	 * @return
	 * @throws Exception
	 */
	@RequestMapping({ "/p/{site}/index.html", "/p/{site}" })
	public String toPortalSiteIndex(Map<String, Object> model, HttpServletRequest request,
	        @PathVariable("site") String site) throws Exception {
		return getView("p", site, "welcome", "index.html", model, request);
	}

	private void pushParameters(Map<String, Object> model, HttpServletRequest request) {
		Enumeration<String> names = request.getParameterNames();
		while (names.hasMoreElements()) {
			String name = names.nextElement();
			String[] values = request.getParameterValues(name);
			if (values != null) {
				if (values.length == 0) {
					model.put(name, "");
				} else if (values.length == 1) {
					model.put(name, values[0]);
				} else {
					model.put(name, values);
				}
			} else {
				model.put(name, "");
			}
		}
	}

	/**
	 * 页面类型的访问均被这个RequestMapper所捕获，前缀是/p。<br>
	 * 这个处理器会把页面访问转发给正确的视图，并将请求过程中得到的中间变量传递给视图。<br>
	 * 栏目的配置等同样通过ModelMap传递到引擎当中，并在小组件的处理调用中使用这些数据。
	 * 
	 * @param model
	 * @param site
	 * @param channel
	 * @param page
	 * @return
	 * @throws Exception
	 */
	@RequestMapping("/p/{site}/{channel}/{page}.html")
	public String toPortalPage(Map<String, Object> model, HttpServletRequest request,
	        @PathVariable("site") String site, @PathVariable("channel") String channel,
	        @PathVariable("page") String page) throws Exception {
		return getView("p", site, channel, page + ".html", model, request);
	}

	/**
	 * 栏目类型的调用将在这里得到处理。当访问一个栏目的根目录时，默认调用其“index.html”。<br>
	 * 既然一个栏目的根目录的调用变成了一个页面的访问，则余下的规则均同页面类型的访问。
	 * 
	 * @param model
	 * @param site
	 * @param channel
	 * @return
	 * @throws Exception
	 */
	@RequestMapping("/p/{site}/{channel}")
	public String toPortalChannel(Map<String, Object> model, HttpServletRequest request,
	        @PathVariable("site") String site, @PathVariable("channel") String channel) throws Exception {
		return getView("p", site, channel, "index.html", model, request);
	}

	// /**
	// * 页面类型的访问均被这个RequestMapper所捕获，前缀是/p。<br>
	// * 这个处理器会把页面访问转发给正确的视图，并将请求过程中得到的中间变量传递给视图。<br>
	// * 栏目的配置等同样通过ModelMap传递到引擎当中，并在小组件的处理调用中使用这些数据。
	// *
	// * @param model
	// * @param site
	// * @param channel
	// * @param page
	// * @return
	// */
	// @RequestMapping("/admin/{site}/{channel}/{page}.html")
	// public String toAdminPortalPage(Map<String, Object> model,
	// @PathVariable("site") String site,
	// @PathVariable("channel") String channel, @PathVariable("page") String
	// page) {
	// model.put(CCMSConstant.KEY_MODEL_MAP, model);
	// return getView("admin", site, channel, page + ".html", model);
	// }

	// /**
	// * 栏目类型的调用将在这里得到处理。当访问一个栏目的根目录时，默认调用其“index.html”。<br>
	// * 既然一个栏目的根目录的调用变成了一个页面的访问，则余下的规则均同页面类型的访问。
	// *
	// * @param model
	// * @param site
	// * @param channel
	// * @return
	// */
	// @RequestMapping("/admin/{site}/{channel}")
	// public String toAdminPortalChannel(Map<String, Object> model,
	// @PathVariable("site") String site,
	// @PathVariable("channel") String channel) {
	// model.put(CCMSConstant.KEY_MODEL_MAP, model);
	// return getView("admin", site, channel, "index.html", model);
	// }
	/**
	 * 这个是页面访问处理的核心，查找能处理的模板映射，并将视图返回回去。<br>
	 * 处理过程中可能产生一些匹配的中间变量，都会加在ModelMap中带给视图，称为视图的全局变量。
	 * 
	 * @param prefix
	 * @param site
	 * @param channel
	 * @param page
	 * @param model
	 * @param request
	 * @return
	 * @throws Exception
	 */
	private String getView(String prefix, String site, String channel, String page, Map<String, Object> model,
	        HttpServletRequest request) throws Exception {
		model.put(CCMSConstant.KEY_MODEL_MAP, model);
		model.put("_prefix_", prefix);
		model.put("_site_", site);
		Site _site = CompletPluginManager.getSite(site);
		if (_site == null) {
			throw new Exception("站点不存在！");
		}
		model.put("_site", _site);
		model.put("_channel_", channel);
		Channel _channel = _site.getChannel(channel);
		if (_channel == null) {
			throw new Exception("栏目不存在！");
		}
		model.put("_channel", _channel);
		model.put("_page_", page);
		pushParameters(model, request);
		String uri = "/" + prefix + "/" + site + "/" + channel + "/" + page;
		ViewMapper vm = ViewMapperCache.getViewMapper(uri);
		if (vm != null) {
			model.put(CCMSConstant.KEY_VIEWMAPPER_IN_MODEL_MAP, vm);
			return getMyView(vm.getView());
		}
		ViewMapResult vmr = ViewMapperCache.getViewMapperResult(uri);
		if (vmr != null) {
			vm = vmr.getMapper();
			String[] variables = vmr.getVariables();
			String[] values = vmr.getValues();
			if (values != null && values.length > 0) {
				for (int i = 0; i < values.length; i++) {
					model.put(CCMSConstant.KEY_PATH_VAR_PREFIX + variables[i], values[i]);
				}
			}
			model.put(CCMSConstant.KEY_VIEWMAPPER_IN_MODEL_MAP, vm);
			return getMyView(vm.getView());
		}
		throw new PageNotFoundException("没有发现匹配的URI请求！");
	}

	private String getMyView(String view) {
		return "ccms/templates/" + view;
	}

	@RequestMapping("/p/500.html")
	public String toErrorPage500() {
		return getMyView("errors/500.ftl");
	}

	@RequestMapping("/p/404.html")
	public String toErrorPage404() {
		return getMyView("errors/404.ftl");
	}

	@RequestMapping("/admin/reload.do")
	@ResponseBody
	@Access("TAG_ROLE_CCMS")
	public String reloadConfigs() {
		CompletPluginManager.getInstance().loadCcmsConfigs();
		return JsonHelper.getSuccessJsonString();
	}
}
